home *** CD-ROM | disk | FTP | other *** search
/ SGI Hot Mix 17 / Hot Mix 17.iso / HM17_SGI / research / lib / read_tiff.pro < prev    next >
Text File  |  1997-07-08  |  11KB  |  335 lines

  1. ; $Id: read_tiff.pro,v 1.4 1997/04/08 14:36:44 dave Exp $
  2. ;
  3. ; Copyright (c) 1991-1997. Research Systems, Inc. All rights reserved.
  4. ;    Unauthorized reproduction prohibited.
  5. ;+
  6. ; NAME:
  7. ;    READ_TIFF
  8. ;
  9. ; PURPOSE:
  10. ;    Read TIFF format images.
  11. ;
  12. ; CATEGORY:
  13. ;    Input/output.
  14. ;
  15. ; CALLING SEQUENCE:
  16. ;   Result = READ_TIFF(Filename [,R, G, B])
  17. ;
  18. ; INPUTS:
  19. ;    Filename:    A string containing the name of file to read.
  20. ;        The default extension is ".TIF".
  21. ;
  22. ; OUTPUTS:
  23. ;    READ_TIFF returns an 8, 16, or 32-bit array containing the image
  24. ;    data.  The dimensions of the result are the same as defined in the TIFF 
  25. ;    file: [Columns, Rows].  The data type of the image is same as
  26. ;    the type of samples in the image file.
  27. ;
  28. ;    For TIFF images that are RGB interleaved by pixel, the output 
  29. ;    dimensions are [3, Cols, Rows].
  30. ;
  31. ;    For TIFF images that are RGB interleaved by image, on output
  32. ;    Planarconfig is set to 2, and the result is the integer value
  33. ;    zero.   In this case, three separate images are returned in
  34. ;    the R, G, and B output parameters.
  35. ;
  36. ; OPTIONAL OUTPUTS:
  37. ;     R, G, B:    Variables to hold the Red, Green, and Blue color vectors
  38. ;        extracted from TIFF Class P, Palette Color images.
  39. ;    For TIFF images that are RGB interleaved by image (Planarconfig
  40. ;    returned as 2) the R, G, and B variables each hold an image
  41. ;    with the dimensions [Columns, Rows].
  42. ;
  43. ; KEYWORDS:
  44. ;    UNSIGNED: If set, return TIFF files containing unsigned 16-bit integers
  45. ;        as signed 32-bit longword arrays.  If not set, return 
  46. ;        a signed 16-bit integer for these files.  In this case,
  47. ;        data values between 32768 and 65535 are returned as 
  48. ;        negative values between -32768 and -1.  This keyword
  49. ;        has no effect if the input file does not contain 16-bit
  50. ;        integers.   To manually convert unsigned 16-bit to 32-bit:
  51. ;            l32 = long(u16)
  52. ;            neg = where(l32 lt 0, count)
  53. ;            if count ne 0 then l32[neg] = 65536 + l32[neg]
  54. ;
  55. ;    The following keywords are used for output parameters only:
  56. ;
  57. ;    ORDER:    The order parameter from the TIFF File.  This parameter is
  58. ;        returned as 0 for images written bottom to top, and 1 for
  59. ;        images written top to bottom.  If the Orientation parameter 
  60. ;        does not appear in the TIFF file, an order of 1 is returned.
  61. ;
  62. ; PLANARCONFIG:    This parameter is returned as 1 for TIFF files that are
  63. ;        GrayScale, Palette, or RGB color interleaved by pixel.  
  64. ;        This parameter is returned as 2 for RGB color TIFF files 
  65. ;        interleaved by image.
  66. ;
  67. ; COMMON BLOCKS:
  68. ;    TIFF_COM.  Only for internal use.
  69. ;
  70. ; SIDE EFFECTS:
  71. ;    A file is read.
  72. ;
  73. ; RESTRICTIONS:
  74. ;    Handles TIFF classes G, P, and R.  One image per file.
  75. ;
  76. ; EXAMPLE:
  77. ;    Read the file "my.tiff" in the current directory into the variable
  78. ;    IMAGE, and save the color tables in the variables, R, G, and B by
  79. ;    entering:
  80. ;
  81. ;        IMAGE = READ_TIFF("my.tiff", R, G, B)
  82. ;
  83. ;    To view the image, load the new color table and display the image by
  84. ;    entering:
  85. ;
  86. ;        TVLCT, R, G, B
  87. ;        TV, IMAGE 
  88. ;
  89. ;
  90. ; MODIFICATION HISTORY:
  91. ;    DMS, Written for VMS in 1985.
  92. ;    DMS, April, 1991.  Rewrote and added class R and P images.
  93. ;    DMS, Jan, 1992.  Fixed bug for images without a RowsPerStrip field.
  94. ;       DJC, Nov, 1993.  Fixed doc header.
  95. ;    DMS, Dec, 1994.     Fixed bug with private tags.
  96. ;    MWR, Mar, 1995.  Fixed bug when opening non-existent file.
  97. ;    DMS, Aug, 1995.  Added support for 16 and 32 bit samples.
  98. ;    DMS, Aug, 1996.  Added UNSIGNED keyword.
  99. ;       SVP, Jan, 1997.  Changed from tiff_read to read_tiff
  100. ;-
  101.  
  102. function tiff_long,a,i,len=len    ;return longword(s) from array a(i)
  103. common tiff_com, order, ifd, count
  104.  
  105.    if n_elements(len) le 0 then len = 1
  106.    if len gt 1 then result = long(a,i,len) $
  107.    else result = long(a,i)
  108.    if order then byteorder, result, /lswap
  109.    return, result
  110. end
  111.  
  112.  
  113. function tiff_rational,a,i, len = len      ; return rational from array a(i)
  114. common tiff_com, order, ifd, count
  115.  
  116. if n_elements(len) le 0 then len = 1
  117. tmp = tiff_long(a, i, len = 2 * len)    ;1st, cvt to longwords
  118. if len gt 1 then begin
  119.     subs = lindgen(len)
  120.     rslt = float(tmp[subs*2]) / tmp[subs*2+1]
  121. endif else rslt = float(tmp[0]) / tmp[1]
  122. return, rslt
  123. end
  124.  
  125. function tiff_int,a,i, len=len    ;return unsigned long int from TIFF short int
  126. common tiff_com, order, ifd, count
  127.  
  128. if n_elements(len) le 0 then len = 1
  129. if len gt 1 then begin    ;Array?
  130.     result = fix(a,i,len)
  131.     if order then byteorder, result, /sswap
  132.     result = long(result)
  133.     if min(result) lt 0 then begin    ;Convert to unsigned from signed 16bit
  134.       negs = where(result lt 0)
  135.       result[negs] = 65536L + result[negs]
  136.       endif
  137. endif else begin    ;Scalar
  138.     result = fix(a,i)
  139.     if order then byteorder, result, /sswap
  140.     if result lt 0 then result = 65536L + result
  141. endelse
  142. return, result
  143. end
  144.  
  145. function tiff_byte, a,i,len=len    ;return bytes from array a(i)
  146. common tiff_com, order, ifd, count
  147.  
  148.    if n_elements(len) le 0 then len = 1
  149.    if len gt 1 then result = a[i:i+len-1] $
  150.    else result = a[i]
  151.    return, result
  152. end
  153.  
  154. function tiff_read_field, index, tag, lun  ;Return contents of field index
  155. ; On output, tag = tiff tag index.
  156. ;
  157. common tiff_com, order, ifd, count
  158.  
  159.  
  160. TypeLen = [0, 1, 1, 2, 4, 8] ;lengths of tiff types, 0 is null type for indexin
  161.  
  162. ent = ifd[index * 12: index * 12 + 11]  ;Extract the ifd
  163. tag = tiff_int(ent, 0)        ;Tiff tag index
  164. typ = tiff_int(ent, 2)        ;Tiff data type
  165. cnt = tiff_long(ent, 4)        ;# of elements
  166. nbytes = cnt * TypeLen[typ]    ;Size of tag field
  167. IF (nbytes GT 4) THEN BEGIN     ;value size > 4 bytes ?
  168.         offset = tiff_long(ent, 8)    ;field has offset to value location
  169.         Point_Lun, lun, offset
  170.         val = BytArr(nbytes)     ;buffer will hold value(s)
  171.         Readu, lun, val
  172.         CASE typ OF        ;Ignore bytes, as there is nothing to do
  173.        1: i = 0        ;Dummy
  174.            2: val = String(val)        ;tiff ascii type
  175.            3: val = tiff_int(val,0, len = cnt)
  176.        4: val = tiff_long(val,0, len = cnt)
  177.            5: val = tiff_rational(val,0, len = cnt)
  178.     ENDCASE
  179. ENDIF ELSE BEGIN            ;Scalar...
  180.         CASE typ OF
  181.        1: val = ent[8]
  182.          2: val = string(ent[8:8+(cnt>1)-1])
  183.        3: val = tiff_int(ent,8)
  184.        4: val = tiff_long(ent,8)
  185.         ENDCASE
  186.      ENDELSE
  187. return, val
  188. end
  189.  
  190.  
  191.  
  192.  
  193. function read_tiff, file, r, g, b, order = ord, PlanarConfig = PC, $
  194.     UNSIGNED=unsigned
  195. common tiff_com, order, ifd, count
  196.  
  197.  
  198. on_error,2                      ;Return to caller if an error occurs
  199.  
  200. openr,lun,file, error = i, /GET_LUN, /BLOCK
  201. if i lt 0 then begin ;OK?
  202.     if keyword_set(lun) then free_lun,lun
  203.     lun = -1
  204.     message, 'Unable to open file: ' + file
  205.     endif
  206.  
  207. hdr = bytarr(8)            ;Read the header
  208. readu, lun, hdr
  209.  
  210. typ = string(hdr[0:1])        ;Either MM or II
  211. if (typ ne 'MM') and (typ ne 'II') then begin
  212.     message,'READ_TIFF: File is not a Tiff file: ' + string(file)
  213.     return,0
  214.     endif
  215. order = typ eq 'MM'          ;1 if Motorola 0 if Intel (LSB first or vax)
  216. endian = byte(1,0,2)        ;What endian is this?
  217. endian = endian[0] eq 0        ;1 for big endian, 0 for little
  218. order = order xor endian    ;1 to swap...
  219.  
  220. ; print,'Tiff File: byte order=',typ, ',  Version = ', tiff_int(hdr,2)
  221.  
  222. offs = tiff_long(hdr, 4)    ;Offset to IFD
  223.  
  224. point_lun, lun, offs        ;Read it
  225.  
  226. a = bytarr(2)            ;Entry count array
  227. readu, lun, a
  228. count = tiff_int(a,0)        ;count of entries
  229. ; print,count, ' directory entries'
  230. ifd = bytarr(count * 12)    ;Array for IFD's
  231. readu, lun, ifd            ;read it
  232.  
  233. ;    Insert default values:
  234. compression = 1
  235. bits_sample = 1
  236. ord = 1
  237. samples_pixel = 1L
  238. pc = 1
  239. photo = 1
  240. rows_strip = 'fffffff'xl    ;Essentially infinity
  241. SampleFormat = 1
  242.  
  243. for i=0,count-1 do begin    ;Print each directory entry
  244.     value = tiff_read_field(i, tag, lun)  ;Get each parameter
  245.     case tag of    ;Decode the tag fields, other tags could be added
  246. 256:    width = value
  247. 257:    length = value
  248. 258:    bits_sample = value[0]
  249. 259:    compression = value
  250. 262:    Photo = value
  251. 273:    StripOff = value
  252. 274:    Ord = value
  253. 277:    samples_pixel = long(value)
  254. 278:    Rows_strip = value
  255. 279:    Strip_bytes = value
  256. 284:    PC = value
  257. 320:    ColorMap = value
  258. 339:    SampleFormat = value
  259. else:   value = 0        ;Throw it away
  260.     endcase
  261. endfor    
  262.  
  263. ;    Do a cursory amount of checking:
  264.     if bits_sample eq 8 then type = 1 $    ;Byte type
  265.     else if bits_sample eq 16 then type = 2 $    ;Short int type
  266.     else if bits_sample eq 32 and SampleFormat le 2 then type = 3 $ ;Long int
  267.     else message,'READ_TIFF: only integer format image handled'
  268.     if compression ne 1 then $
  269.     message,'READ_TIFF: Images must be un-compressed'
  270.     if (pc eq 2) and (samples_pixel ne 3) then $
  271.     message,'READ_TIFF: RGB data must have 3 SamplesPerPlane'
  272.     
  273. strips_image = (length + rows_strip -1) / rows_strip
  274. dims = [width, length]
  275. bytes_sample = bits_sample/8
  276.  
  277. if pc eq 1 then begin    ;Planar Config...., simple
  278.     if samples_pixel gt 1 then dims = [samples_pixel, dims]
  279.     image = make_array(DIMENSION=dims, TYPE=type,  /NOZERO)
  280.     if strips_image eq 1 then begin    ;Quick way?
  281.     point_lun, lun, stripoff[0]   ;1st image data
  282.     readu, lun, image     ;Yes....
  283.     endif else begin        ;1 strip at a time....
  284.     for i=0L, strips_image-1 do begin
  285.         point_lun, lun, stripoff[i]
  286.         if n_elements(tmp)*bytes_sample ne Strip_bytes[i] Then $
  287.           tmp = make_array(Strip_bytes[i]/bytes_sample, TYPE=type, /NOZERO)
  288.         readu, lun, tmp
  289.         image[samples_pixel * width * i * rows_strip] = tmp
  290.         endfor
  291.     endelse
  292.     if n_elements(ColorMap) gt 0 then begin    ;Color map present?
  293.        if n_elements(ColorMap) eq 768 then begin
  294.         r = ishft(ColorMap[0:255], -8) ;Remove and scale
  295.         g = ishft(ColorMap[256:511], -8)
  296.         b = ishft(ColorMap[512:767], -8)
  297.         endif else message,'READ_TIFF: color map has wrong # of elements'
  298.     endif
  299.  
  300.     if order and (bytes_sample eq 2) then BYTEORDER, image, /SSWAP
  301.     if order and (bytes_sample eq 4) then BYTEORDER, image, /LSWAP
  302.  
  303. endif else begin            ;PC = 2, = interleaved by image
  304.     l = 0
  305.     for band = 0,2 do begin        ;Read each image
  306.     image = make_array(DIMENSION=dims, TYPE=type,  /NOZERO)
  307.     for i=0L, strips_image-1 do begin
  308.         point_lun, lun, stripoff[l]
  309.         if n_elements(tmp)*bytes_sample ne Strip_bytes[l] then $
  310.           tmp = make_array(Strip_bytes[i]/bytes_sample, TYPE=type, /NOZERO)
  311.         readu, lun, tmp
  312.         image[width * i * rows_strip] = tmp
  313.         l = l + 1
  314.         endfor        ;Each strip
  315.     if order and (bytes_sample eq 2) then BYTEORDER, image, /SSWAP
  316.     if order and (bytes_sample eq 4) then BYTEORDER, image, /LSWAP
  317.     case band of
  318.       0: r = temporary(image)
  319.       1: g = temporary(image)
  320.       2: b = temporary(image)
  321.         endcase
  322.         image = 0
  323.     endfor                ;Each band
  324. endelse                    ;PC = 2
  325.     
  326. if bits_sample eq 16 and keyword_set(unsigned) then begin
  327.     image = long(image)
  328.     neg = where(image lt 0, count)
  329.     if count gt 0 then image[neg] = 65536L + image[neg]
  330.     endif
  331.  
  332. free_lun, lun
  333. return, image
  334. end
  335.